﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace StockLearner
{
    class NNAgent: Agent
    {
        NeuralNetwork net;

        double rewardSum;
        TextWriter tw;

        public NNAgent():base()
        {
            net = new NeuralNetwork(30, 10, 1, 0.01);
            tw = new StreamWriter("nn.txt");
        }

        // returns list of one point that is the prediction for in 30 minutes
        public override List<YahooDataPoint> act(List<YahooDataPoint> p_state)
        {
            List<Double> ret = net.input(pointsToDoubles(p_state));
            //double[] ret = net.input(pointsToDouble(p_state));
            YahooDataPoint point = p_state[0];
            point.Close = ret[0] + 0.5;
            Trace.WriteLine(point.Close);

            //DateTime t = Utils.UnixTimeStampToDateTime(point.Timestamp);
            //t = t.AddMinutes(30);
            //point.Timestamp = (int)Utils.DateTimeToUnixTimestamp(t);
            point.Timestamp = Utils.AddMinutesUnixTimeStamp(point.Timestamp, 30.0);

            List<YahooDataPoint> list = new List<YahooDataPoint>();
            list.Add(point);
            return list;
        }

        public override void processReward(List<YahooDataPoint> my_prediction, List<YahooDataPoint> state, List<YahooDataPoint> result)
        {
            List<double> inputs = pointsToDoubles(Form1.GeneralizeAndDiscretize(state));
            List<YahooDataPoint> l = Form1.GeneralizeAndDiscretize(result);
            List<double> outputs = pointsToDoubles(Form1.GeneralizeAndDiscretize(result).Skip(29).Take(1).ToList());
            outputs[0] -= 0.5;
            if (outputs[0] > 2)
            {
                Trace.WriteLine("expected value below 2");
                return;
            }
            double ret = net.train(inputs, outputs);

            rewardSum += ret;
            tw.WriteLine(ret);
            //double[] inputs = pointsToDoublea(state);
            //double[] target = pointsToDouble(result);
            //d/ouble[] target2 = new double[1];
            //target2[0] = target.Last();
            //tw.WriteLine(net.train(inputs, target2));
        }

        public List<double> pointsToDoubles(List<YahooDataPoint> list)
        {
            List<double> ret = new List<double>();
            for (int i = 0; i < list.Count; i++)
            {
                ret.Add(list[i].Close);
            }
            return ret;
        }

        public override void saveKnowledge()
        {
            tw.Close();
        }

        public void resetRewardSum()
        {
            rewardSum = 0;
        }

        public double getRewardSum()
        {
            return rewardSum*rewardSum;
        }
    }
}
